package com.ifp.opengate.boot.utils;

import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.lang.StringUtils;
import org.apache.dubbo.config.ApplicationConfig;
import org.apache.dubbo.config.ReferenceConfig;
import org.apache.dubbo.config.RegistryConfig;
import org.apache.dubbo.rpc.service.GenericService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import com.ifp.core.flow.service.FlowService;
import com.ifp.core.log.Trace;
import com.ifp.core.util.StringUtil;
import com.ifp.opengate.boot.constants.Constants;

/**
 * <p>
 * Title: ifp rpc 服务生成工具类 <／p>
 * <p>
 * Company: YNET<／p>
 *
 * @author liangmin
 * @date 2018-3-28
 */
@Component("ifpRpcServiceUtil")
@Order(1)
public class IfpRpcServiceUtil {
    /**
     * ifp rpc 服务接口类
     */
    public final static String IFP_RPC_SERVICE_INF = "com.ifp.core.flow.service.FlowService";
    /**
     * ifp rpc 服务实现类
     */
    private final static String IFP_RPC_SERVICE_IMP = "com.ynet.connectbank.rpc.service.ConnectbankFlowServiceImp";

    @Value("${dubbo.service.timeout:180000}")
    public int serviceTimeout;

    @Autowired
    private ApplicationContext applicationContext;
    org.apache.curator.framework.CuratorFrameworkFactory a;

    @Autowired
    private ApplicationConfig application;

    public GenericService deployDubboRpcCustomer(String actionName, String serviceName, String version,
        Map<String, Object> o) {
        Trace.log(Trace.MODULE_FILTER, Trace.LEVEL_INFO, "网关发布Dubbo服务" + actionName);

        String interfaceClazz = "com.ifp.core.flow.service.FlowService";
        String serviceRetries = "3";
        String serviceCode = StringUtils.EMPTY;

        if (o.containsKey("tempMap")) {
            Map<String, Object> tempMap = (Map<String, Object>)o.get("tempMap");

            // interface
            if (tempMap.containsKey(Constants.SUBCRIBE_CLASS)) {
                interfaceClazz = (String)tempMap.get(Constants.SUBCRIBE_CLASS);
            }
            // serviceRetries
            if (tempMap.containsKey(Constants.SUBCRIBE_RETRIES)) {
                serviceRetries = (String)tempMap.get(Constants.SUBCRIBE_RETRIES);
            }
            // interface
            if (tempMap.containsKey(Constants.SUBCRIBE_SERVICE_CODE)) {
                serviceCode = (String)tempMap.get(Constants.SUBCRIBE_SERVICE_CODE);
            }
        }

        // retries
        Integer retries = 0;
        if (StringUtils.isNotEmpty(serviceRetries)) {
            String regex = "^[1-3]$";
            Pattern p = Pattern.compile(regex);
            Matcher m = p.matcher(serviceRetries);
            if (m.find()) {
                retries = Integer.valueOf(serviceRetries);
            }
        }

        DefaultListableBeanFactory beanFactory =
            (DefaultListableBeanFactory)applicationContext.getAutowireCapableBeanFactory();
        try {
            ReferenceConfig<GenericService> reference = new ReferenceConfig<GenericService>();

            reference.setApplication(application);
            reference.setId(serviceCode);
            reference.setInterface(interfaceClazz);
            // group
            if (StringUtils.isNotEmpty(serviceName)) {
                reference.setGroup(serviceName);
            }
            // version
            if (StringUtils.isNotEmpty(version)) {
                reference.setVersion(version);
            }
            reference.setRetries(retries);
            reference.setTimeout(serviceTimeout);
            reference.setGeneric(true);

            // 用org.apache.dubbo.rpc.service.GenericService可以替代所有接口引用
            GenericService genericService = reference.get();
            beanFactory.destroySingleton(serviceName + version + Constants.SUBSCRIBER);
            beanFactory.registerSingleton(serviceName + version + Constants.SUBSCRIBER, genericService);
            return genericService;
        } catch (Exception e) {
            beanFactory.destroySingleton(serviceName);
            Trace.logInfo(Trace.MODULE_INTERCEPTOR, "subscribeDubboRpcService[{}-{}]  error! ", serviceName, version,
                e);
        }
        return null;

    }

    /**
     * <p>
     * Title: pushDubbovService
     * </p>
     * <p>
     * Description: 根据服务编码、服务版本号 发布单个服务
     * </p>
     *
     * @param serviceCode 服务编号
     * @param serviceVersion 服务版本号
     */
    public FlowService deployRpcCustomer(String serviceCode, String serviceVersion, String serviceName,
        RegistryConfig registry) {
        Trace.logInfo(Trace.MODULE_RPC, "deploy Refrence .. serviceCode={},serviceVersion={}", serviceCode,
            serviceVersion);
        // Transaction t = Cat.getProducer().newTransaction("Dynamic.deploy", "[" + serviceCode + "]" + serviceName);
        // t.setStatus("0");
        DefaultListableBeanFactory beanFactory =
            (DefaultListableBeanFactory)applicationContext.getAutowireCapableBeanFactory();

        // 订阅内部接口
        ReferenceConfig<FlowService> reference = new ReferenceConfig<FlowService>();
        reference.setApplication(application);
        reference.setRegistry(registry);
        try {
            reference.setId(serviceCode);
            reference.setInterface(FlowService.class);
            reference.setGroup(serviceCode);
            reference.setVersion(serviceVersion);
            reference.setRetries(0);
            reference.setTimeout(serviceTimeout);
            reference.setFilter("DubboConsumerFilter");
            FlowService flowService = reference.get();
            beanFactory.destroySingleton(serviceCode + Constants.SUBSCRIBER);
            beanFactory.registerSingleton(serviceCode + Constants.SUBSCRIBER, flowService);
            return flowService;
        } catch (Exception e) {
            beanFactory.destroySingleton(serviceCode);
            // Cat.logError(e);
            Trace.logInfo(Trace.MODULE_INTERCEPTOR, "subscribeRpcService[{}-{}]  error! ", serviceCode, serviceVersion,
                e);
        } finally {
            // t.complete();
        }
        Trace.logInfo(Trace.MODULE_RPC, "deploy service success .. serviceCode={},serviceVersion={}", serviceCode,
            serviceVersion);
        return null;
    }

    public RegistryConfig deployRegistry(String serviceCode, String serviceName, String address, String username,
        String password) {
        Trace.logInfo(Trace.MODULE_RPC, "deploy Refrence .. serviceCode={}", serviceCode);
        // Transaction t = Cat.getProducer().newTransaction("Dynamic.deploy", "[" + serviceCode + "]" + serviceName);
        // t.setStatus("0");
        DefaultListableBeanFactory beanFactory =
            (DefaultListableBeanFactory)applicationContext.getAutowireCapableBeanFactory();
        try {
            // 连接注册中心配置
            RegistryConfig registry = new RegistryConfig();
            registry.setAddress(address);
            if (StringUtil.hasText(username) && StringUtil.hasText(password)) {
                registry.setUsername(username);
                registry.setPassword(password);
            }
            registry.setId(serviceCode + Constants.REGISTRY_CONFIG);
            registry.setCheck(false);
            registry.setFile("false");
            beanFactory.destroySingleton(serviceCode + Constants.REGISTRY_CONFIG);
            beanFactory.registerSingleton(serviceCode + Constants.REGISTRY_CONFIG, registry);
            return registry;
        } catch (Exception e) {
            beanFactory.destroySingleton(serviceCode + Constants.REGISTRY_CONFIG);
            // Cat.logError(e);
            Trace.logInfo(Trace.MODULE_INTERCEPTOR, "RegistryConfig[{}]  error! ", serviceCode, e);
        } finally {
            // t.complete();
        }
        return null;
    }

    public void deployRpcCustomer(String serviceCode, String serviceVersion, String serviceName, Class clazz,
        RegistryConfig registry) {
        Trace.logInfo(Trace.MODULE_RPC, "deploy Refrence .. serviceCode={},serviceVersion={}", serviceCode,
            serviceVersion);
        // Transaction t = Cat.getProducer().newTransaction("Dynamic.deploy", "[" + serviceCode + "]" + serviceName);
        DefaultListableBeanFactory beanFactory =
            (DefaultListableBeanFactory)applicationContext.getAutowireCapableBeanFactory();
        // t.setStatus("0");
        // 订阅内部接口
        ReferenceConfig<FlowService> reference = new ReferenceConfig<FlowService>();
        reference.setApplication(application);
        reference.setRegistry(registry);
        try {
            reference.setId(serviceCode);
            reference.setInterface(clazz);
            reference.setGroup(serviceCode);
            reference.setVersion(serviceVersion);
            reference.setRetries(0);
            reference.setTimeout(serviceTimeout);
            FlowService flowService = reference.get();
            beanFactory.destroySingleton(serviceCode);
            beanFactory.registerSingleton(serviceCode, flowService);
        } catch (Exception e) {
            beanFactory.destroySingleton(serviceCode);
            // Cat.logError(e);
            Trace.logInfo(Trace.MODULE_INTERCEPTOR, "subscribeRpcService[{}-{}]  error! ", serviceCode, serviceVersion,
                e);
        } finally {
            // t.complete();
        }

        Trace.logInfo(Trace.MODULE_RPC, "deploy service success .. serviceCode={},serviceVersion={}", serviceCode,
            serviceVersion);
    }

}
